package foxy.niosocket;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;

import foxy.jpush.Constant;
import foxy.jpush.Utils;

public class NioSocketConnection implements NioSocket {
	private static final boolean DEBUG=true;
	private static final String TAG=NioSocketConnection.class.getName();
	 
	protected Selector selector;
	protected SocketChannel socketChannel;
	private String nsHost;
	private int nsPort;
	private byte[] header;
	private boolean mActive;
	private ConnectionHandler nsHandler;
	
	@Override
	public void connect(String url, ConnectionHandler nsHandler) {
		this.nsHandler=nsHandler;
		String[] parameters=url.split(":");
		nsHost=parameters[0];
		nsPort=Integer.parseInt(parameters[1]);
		 try {
			socketChannel=SocketChannel.open(new InetSocketAddress(nsHost, nsPort));
			socketChannel.configureBlocking(false);			//设置为非阻塞模式
			selector=Selector.open();
			socketChannel.register(selector, SelectionKey.OP_READ);
			mActive=true;
			
			new NioSocketReceiveThread(this);
			nsHandler.onOpen();
		} catch (IOException e) {
			nsHandler.onClose(ConnectionHandler.CLOSE_CANNOT_CONNECT, "Connection could not be established in the first place");
			mActive=false;
			this.disConnect();
			e.printStackTrace();
		}
		
	}
		

	@Override
	public void disConnect() {
		mActive = false; 
	     try {
	    	 if(socketChannel!=null){
				socketChannel.close();
				socketChannel=null;
    		 }	    		 
	    	 if(selector!=null){
				 selector.close();
				 selector=null;
    		 }
	    	 } catch (IOException e) {
				e.printStackTrace();
		}

	}
	
	@Override
	public boolean isConnected() {
		if(this.socketChannel!=null){
			return this.socketChannel.isConnected();
		}
		return false;
	}

	@Override
	public void sendBinaryMessage(byte[] payload) {
		ByteBuffer writeBuffer=ByteBuffer.wrap(payload);
		//writeBuffer.put(payload);
		try {
			socketChannel.write(writeBuffer);
		} catch (IOException e) {
			this.mActive=false;
			this.disConnect();
			this.nsHandler.onClose(ConnectionHandler.CLOSE_CONNECTION_LOST, "A previously established connection was lost unexpected");
			e.printStackTrace();
		}

	}

	@Override
	public void sendRawTextMessage(byte[] payload) {
		sendBinaryMessage(payload);
	}

	@Override
	public void sendTextMessage(String payload) {
		try {
			ByteBuffer writeBuffer = ByteBuffer.wrap(payload.getBytes("UTF-8"));
			socketChannel.write(writeBuffer);
		} catch (IOException e) {
			this.mActive=false;
			this.disConnect();
			this.nsHandler.onClose(ConnectionHandler.CLOSE_CONNECTION_LOST, "A previously established connection was lost unexpected");
			e.printStackTrace();
		}
		  
	}

	@Override
	public void sendPingFrame() {
		byte[] data={0x01};
		byte[] result=null;
		result = Utils.getSendPagectFromInt(data, Constant.DataType.LPUSH_HEADER_TYPE_HREATBEAT);
		sendBinaryMessage(result);
		
	}

	public Selector getSelector() {
		return selector;
	}

	public void setSelector(Selector selector) {
		this.selector = selector;
	}
	public SocketChannel getSocketChannel() {
		return socketChannel;
	}

	public void setSocketChannel(SocketChannel socketChannel) {
		this.socketChannel = socketChannel;
	}

	public boolean ismActive() {
		return mActive;
	}







	public void setmActive(boolean mActive) {
		this.mActive = mActive;
	}







	public ConnectionHandler getNsHandler() {
		return nsHandler;
	}







	public void setNsHandler(ConnectionHandler nsHandler) {
		this.nsHandler = nsHandler;
	}

	
	

}
